﻿namespace EFS.RC.CCC.Applications.EndPoints.OfficeService
{
	/// <summary>
	/// Gateway End Point
	/// </summary>
	internal class Gateway : EFS.RC.CCC.Applications.EndPoints.Presence<EFS.RC.CCC.Deployment.Entities.EndPoints.Gateway, EFS.RC.CCC.Presences.EndPoints.OfficeService.Gateway>	
	{
		#region Composition

		// End point setting
		protected Microsoft.Rtc.Collaboration.ApplicationEndpointSettings applicationEndpointSettings = null;

		#endregion

		#region Constructor

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="ownerUri"></param>
		public Gateway(
			Microsoft.Rtc.Collaboration.ApplicationEndpointSettings applicationEndpointSettings,
			EFS.RC.CCC.Presences.EndPoints.OfficeService.Gateway gatewayEndPointPresence)
			: base(gatewayEndPointPresence)
		{
			// distribution
			EFS.Common.Verify.Reference(applicationEndpointSettings, "applicationEndpointSettings");
			
			// set
			this.applicationEndpointSettings = applicationEndpointSettings;

			// set
			applicationEndpointSettings.IsDefaultRoutingEndpoint = false;
			applicationEndpointSettings.AutomaticPresencePublicationEnabled = false;
			applicationEndpointSettings.Presence.PreferredServiceCapabilities = null;
			applicationEndpointSettings.UseRegistration = false;

			// log
			EventLog.Log.LogInfo("OfficeService", this);
		}

		#endregion

		#region Delegates

		/// <summary>
		/// Service shutting down delegate
		/// </summary>
		/// <param name="agentHunter"></param>
		/// <returns></returns>
		public delegate void ShuttingDown(EFS.RC.CCC.Applications.EndPoints.OfficeService.Gateway gatewayOfficeServiceEndPoint);

		/// <summary>
		/// Service shutting down delegate registrar
		/// </summary>
		public ShuttingDown OnShuttingDown = null;

		#endregion

		#region Usage

		/// <summary>
		/// Agents end point
		/// </summary>
		public EFS.RC.CCC.Applications.EndPoints.OfficeService.Operators OfficeServiceOperatorsEndPointApplication
		{
			get
			{
				// presence knows operators presence as well
				return ApplicationPresence.EndPointsPresencesRegistrar.OperatorOfficeServiceEndPointPresence.PresenceEndPointApplication;
			}
		}

		/// <summary>
		/// Deployment reload
		/// </summary>
		/// <returns></returns>
		public void ReloadDeployment()
		{
		}

		#endregion

		#region Startup

		/// <summary>
		/// Get app end point settings
		/// </summary>
		protected override Microsoft.Rtc.Collaboration.ApplicationEndpointSettings ApplicationEndpointSettings 
		{
			get { return applicationEndpointSettings; } 
		}

		/// <summary>
		/// End point active
		/// </summary>
		protected override void PostEndPointEstablish(Microsoft.Rtc.Collaboration.ApplicationEndpoint collaborationApplicationEndpoint)
		{
			// log
			EFS.EventLog.Log.LogInfo("PostEndPointEstablish", this);

			// check
			EFS.Common.Verify.Reference(collaborationApplicationEndpoint, "collaborationApplicationEndpoint");

			// register for audio/video calls
			collaborationApplicationEndpoint.RegisterForIncomingCall<Microsoft.Rtc.Collaboration.AudioVideo.AudioVideoCall>(OnIncomingAudioVideoCallCalls);
		}

		#endregion

		#region Runtime

		/// <summary>
		/// On incomming audio-video calls
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="args"></param>
		private void OnIncomingAudioVideoCallCalls(object sender, Microsoft.Rtc.Collaboration.CallReceivedEventArgs<Microsoft.Rtc.Collaboration.AudioVideo.AudioVideoCall> args)
		{
			EFS.EventLog.Log.LogInfo("OnIncomingAudioVideoCallCalls", this);

			try
			{
				// Must be new call (agent)
				if (args.IsNewConversation && args.CallToBeReplaced == null)
				{
					// get agent
					EFS.RC.CCC.Presences.Operators.Presence presence = ApplicationPresence.
						EndPointsPresencesRegistrar.
						OperatorOfficeServiceEndPointPresence.
						PresenceEndPointApplication.
						OperatorsTeam.
						GetAgentBySIP(args.Call.RemoteEndpoint.Participant.Uri);

					// check
					if (null == presence)
					{
						// make anon operator
						presence = new EFS.RC.CCC.Presences.Operators.Annonimous(args.Call.RemoteEndpoint.Participant.Uri, 
							ApplicationPresence.EndPointsPresencesRegistrar.OperatorOfficeServiceEndPointPresence.PresenceEndPointApplication.Domain);
					}

					// check
					if (null != presence)
					{
						// get a dial end point
						EFS.RC.CCC.Presences.EndPoints.OfficeService.Customer gatewayOfficeServiceEndPointPresence =
							ApplicationPresence.EndPointsPresencesRegistrar.GetDialOutCustomerOfficeServicePresence();

						// check
						if (null != gatewayOfficeServiceEndPointPresence)
						{
							// make a dialout agent session
							EFS.RC.CCC.Sessions.Operators.DialOut operatorSession = new EFS.RC.CCC.Sessions.Operators.DialOut(
								presence,
								gatewayOfficeServiceEndPointPresence.PresenceEndPointApplication,
								args.Call,
								args.RequestData.FromHeader.DisplayName);

							// if agent, register
							if (presence is EFS.RC.CCC.Presences.Operators.OfficeService.Agent)
							{
								// register
								(presence as EFS.RC.CCC.Presences.Operators.OfficeService.Agent).RegisterDialOutSession(operatorSession);
							}

							// start agent session
							operatorSession.BeginStartup();
						}
						else
						{
							// decline
							args.Call.Decline();
						}
					}
					else
					{
						// decline
						args.Call.Decline();
					}
				}
				else
				{
					// decline
					args.Call.Decline();
				}
			}
			catch (System.Exception ex)
			{
				// log
				EFS.EventLog.Log.LogException(ex, this);

				// decline
				args.Call.Decline();
			}
		}

		#endregion

		#region Shutdown

		/// <summary>
		/// Clean-up 
		/// </summary>
		/// <param name="collaborationApplicationEndpoint"></param>
		protected override void PreEndPointTerminate(Microsoft.Rtc.Collaboration.ApplicationEndpoint collaborationApplicationEndpoint)
		{
			// log
			EFS.EventLog.Log.LogInfo("PreEndPointTerminate", this);

			// check
			EFS.Common.Verify.Reference(collaborationApplicationEndpoint, "collaborationApplicationEndpoint");

			//unregister the events
			collaborationApplicationEndpoint.UnregisterForIncomingCall<Microsoft.Rtc.Collaboration.AudioVideo.AudioVideoCall>(OnIncomingAudioVideoCallCalls);

			// notify delegates
			if (null != OnShuttingDown)
			{
				try
				{
					OnShuttingDown(this);
				}
				catch (System.Exception ex)
				{
					// log
					EFS.EventLog.Log.LogException(ex, this);
				}
			}
		}

		/// <summary>
		/// Stopped 
		/// </summary>
		/// <param name="collaborationApplicationEndpoint"></param>
		protected override void EndPointStopped()
		{
			// log
			EFS.EventLog.Log.LogInfo("EndPointStopped", this);
		}

		#endregion
	}
}
